/**
 * Copyright (c) 2016-2019  All rights reserved.
 * <p>
 *
 * <p>
 * 版权所有，侵权必究！
 */

package io.yuncheng.modules.job.task;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import io.yuncheng.common.config.DictConfig;
import io.yuncheng.common.utils.Constant;
import io.yuncheng.common.utils.HttpClientUtils;
import io.yuncheng.common.utils.OuterServerUrlConstant;
import io.yuncheng.common.utils.SysDictConstant;
import io.yuncheng.modules.job.entity.ResponseAppListEntity;
import io.yuncheng.modules.job.entity.ResponseDeptListEntity;
import io.yuncheng.modules.job.entity.ResponseEntity;
import io.yuncheng.modules.sys.entity.*;
import io.yuncheng.modules.sys.service.*;
import io.yuncheng.modules.sys.entity.*;
import io.yuncheng.modules.sys.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 同步部门以及应用
 * 1.查询枚举表查询是否是省级平台
 * 2.非省级平台获取省级平台url
 * 3.查询机构-一级 二级 应用 机构-调用新增/修改
 * 3.查询应用-调用新增修改
 *
 * @author
 */
@Component("syncApplicationTask")
public class SyncApplicationTask implements ITask {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private DictConfig config;
    @Resource
    private SysDeptService sysDeptService;
    @Autowired
    private SubApplicationService applicationService;
    @Resource
    private SubAppLogCollectService subAppLogCollectService;

    @Resource
    private SubAppAssessmentSplitService subAppAssessmentSplitService;
    /**
     * 后续初始化
     */
    private String server = "";
    @Resource
    private SubCascadePlatformLogService subCascadePlatformLogService;

    @Resource
    AppTaskImpl appTask;

    @Resource
    private SubAppWarnLogService subAppWarnLogService;

    @Override
    public void run(String params) {
        //省级平台不做操作
        String deptIdStr = config.getSysDictValue(SysDictConstant.SYS_LEVEL, Constant.DICT_DEFAULT_CODE);
        Integer deptId = Integer.valueOf(deptIdStr);
        if (deptId == Constant.SysLevelEnum.PROVINCE.getValue()) {
            logger.info("省级平台不需要上传数据");
            return;
        }
        SysDictEntity sysDict = config.getSysDict(SysDictConstant.SYS_LEVEL_TYPE, Constant.DICT_DEFAULT_CODE);
        server = sysDict.getRemark();
        //同步部门
        syncDept(deptIdStr, server + OuterServerUrlConstant.DEPT_LIST);
        //同步应用
        syncApp(deptIdStr, server + OuterServerUrlConstant.APP_LIST);
        //同步应用数据
        appTask.run("{}");
        //记录级联日志
        saveCascade(deptIdStr,server + OuterServerUrlConstant.CASCADE_LOG_SAVE);
    }
    /**
     * 同步算法日志
     * @param dept
     * @param rootDeptId
     * @param serverUrl
     */
    void syncArithLog(Long appId,Long dept,Long rootDeptId,String serverUrl){
        for (SubAppLogCollectEntity subAppLogCollectEntity : subAppLogCollectService.queryListByAppId(appId)) {
            SubAppLogCollectOuterEntity entity = subAppLogCollectEntity.buildByOuterEntity(dept, rootDeptId);
            HttpClientUtils.postHttp(serverUrl, JSON.toJSONString(entity));
        }
    }
    /**
     *  同步密评 TODO
     * @param appId
     * @param rootDeptId
     * @param serverUrl
     */
    void syncAssessment(Long appId,Long dept, Long rootDeptId,String serverUrl){
        List<SubAppAssessmentSplitEntity> list = subAppAssessmentSplitService.queryListByEntityAllByAppId(appId);
        Map<Date, List<SubAppAssessmentSplitEntity>> collect = list.stream().collect(Collectors.groupingBy(SubAppAssessmentSplitEntity::getAssessmentDate));
        for (Map.Entry<Date, List<SubAppAssessmentSplitEntity>> dateListEntry : collect.entrySet()) {
            SubAppAssessmentSplitOuterEntity subAppAssessmentSplitOuterEntity = new SubAppAssessmentSplitOuterEntity();
            subAppAssessmentSplitOuterEntity.setDeptId(dept);
            subAppAssessmentSplitOuterEntity.setAssessmentDate(dateListEntry.getKey());
            subAppAssessmentSplitOuterEntity.setRootDeptId(rootDeptId);
            subAppAssessmentSplitOuterEntity.setSplitEntities(dateListEntry.getValue());
            HttpClientUtils.postHttp(serverUrl, JSON.toJSONString(subAppAssessmentSplitOuterEntity));
        }
    }
    /**
     *  告警日志 todo
     * @param uniqueAppId
     * @param rootDeptId
     * @param serverUrl
     */
    void syncWarningLog(String uniqueAppId,Long dept, Long rootDeptId,String serverUrl){
        //查询上次级联上报的时间

        Date date = subCascadePlatformLogService.queryMaxTime();
        QueryWrapper<SubAppWarnLogEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_unique_id",uniqueAppId).ge(date!=null,"create_date",date);
        List<SubAppWarnLogEntity> list = subAppWarnLogService.list(queryWrapper);
        Lists.partition(list,50).forEach(a->{
            OuterAppWarnLogList outerAppWarnLogList = new OuterAppWarnLogList();
            outerAppWarnLogList.setDeptId(dept);
            outerAppWarnLogList.setRootDeptId(rootDeptId);
            outerAppWarnLogList.setAgentWarningLogEntities(a);
            HttpClientUtils.postHttp(serverUrl, JSON.toJSONString(outerAppWarnLogList));

        });
    }


    /**
     * 上传级联日志记录 保存本地级联日志
     * @param deptId
     * @param serverUrl
     */
    void saveCascade(String deptId,String serverUrl){
        SubCascadePlatformLogEntity entity  = new SubCascadePlatformLogEntity();
        //接收方
        entity.setCascadeType(Constant.SysLevelEnum.PROVINCE.getValue());
        entity.setCascadeStatus(2);
        entity.setCascadeId(Long.valueOf(deptId));
        entity.setCascadeTime(new Date());
        HttpClientUtils.postHttpResult(serverUrl, JSON.toJSONString(entity));

        //发送方
        SubCascadePlatformLogEntity entityLocal  = new SubCascadePlatformLogEntity();
        //接收方
        entityLocal.setCascadeType(Constant.SysLevelEnum.CITY.getValue());
        entityLocal.setCascadeStatus(2);
        entityLocal.setCascadeId(Long.valueOf(deptId));
        entityLocal.setCascadeTime(new Date());
        subCascadePlatformLogService.save(entityLocal);

    }

    public void syncApp(String levelDept, String url) {
        List<SysDeptEntity> list = sysDeptService.list();
        List<Long> filterOne = list.stream().filter(a -> a.getParentId().equals(Long.valueOf(levelDept)) && a.getType().equals(Constant.DeptTypeEnum.DEPT_1.getValue())).map(a -> a.getDeptId()).collect(Collectors.toList());
        List<Long> filterTow = list.stream().filter(a -> filterOne.contains(a.getParentId()) && a.getType().equals(Constant.DeptTypeEnum.DEPT_2.getValue())).map(a -> a.getDeptId()).collect(Collectors.toList());
        filterOne.addAll(filterTow);
        List<SubApplicationEntity> appListCity = applicationService.list();
        List<SubApplicationEntity> appList = appListCity.stream().filter(a -> filterOne.contains(a.getParentDeptId())).collect(Collectors.toList());
        String appProvinceStr = HttpClientUtils.postHttp(url, "");
        ResponseAppListEntity responseAppListEntity = JSON.parseObject(appProvinceStr, ResponseAppListEntity.class);
        List<SubApplicationEntity> appListProvince = responseAppListEntity.getData();
        Map<String, SubApplicationEntity> province = appListProvince.stream().collect(Collectors.toMap(SubApplicationEntity::getUniqueId, a -> a, (k1, k2) -> k1));
        for (SubApplicationEntity applicationEntity : appList) {
            SubApplicationEntity subApplicationEntity = new SubApplicationEntity();
            BeanUtils.copyProperties(applicationEntity, subApplicationEntity);
            //对应的机构
            SysDeptEntity querySysDept = new SysDeptEntity();
            querySysDept.setUniqueId(levelDept + "-" + subApplicationEntity.getDeptId());
            String deptStr = HttpClientUtils.postHttp(server + OuterServerUrlConstant.DEPT_INFO, JSON.toJSONString(querySysDept));
            SysDeptEntity deptEntity = JSON.parseObject(deptStr, SysDeptEntity.class);
            if (deptEntity == null) {
                logger.info("对应dept未同步");
            }
            subApplicationEntity.setDeptId(deptEntity.getDeptId());
            subApplicationEntity.setParentDeptId(deptEntity.getParentId());
            subApplicationEntity.setUniqueId(levelDept + "-" +subApplicationEntity.getAppId());
            //监管平台的app
            SubApplicationEntity entity = province.get(levelDept + "-" + subApplicationEntity.getAppId());
            if (entity != null) {
                subApplicationEntity.setAppId(entity.getAppId());
                ResponseEntity responseEntity = HttpClientUtils.postHttpResult(server + OuterServerUrlConstant.APP_UPDATE, JSON.toJSONString(subApplicationEntity));
                logger.info("应用更新 ："+JSON.toJSONString(responseEntity));

            }
            if (entity == null) {
                subApplicationEntity.setAppId(null);
                ResponseEntity responseEntity = HttpClientUtils.postHttpResult(server + OuterServerUrlConstant.APP_SAVE, JSON.toJSONString(subApplicationEntity));
                logger.info("应用保存 ："+JSON.toJSONString(responseEntity));
            }
        }
    }

    /**
     * 同步部门
     *
     * @param deptIdStr
     */
    public void syncDept(String deptIdStr, String url) {
        Long deptIdLong = Long.valueOf(deptIdStr);

        List<Long> longs = Arrays.asList(deptIdLong);
        //查询所有的平台
        String deptProvince = HttpClientUtils.postHttp(url, "");
        ResponseDeptListEntity responseDataEntity = JSON.parseObject(deptProvince, ResponseDeptListEntity.class);
        List<SysDeptEntity> data = responseDataEntity.getData();
        //监管平台的数据
        List<SysDeptEntity> levelTypeOneProvince = filterByParentAndDept(data, longs, Constant.DeptTypeEnum.DEPT_1);
        List<SysDeptEntity> levelTypeTwoProvince = filterByParentAndDept2(data, levelTypeOneProvince);
        List<SysDeptEntity> levelTypeAPPProvince = filterByParentAndDept99(data, levelTypeTwoProvince);
        List<SysDeptEntity> deptList = sysDeptService.list();
        List<SysDeptEntity> levelTypeOne = filterByParentAndDept(deptList, longs, Constant.DeptTypeEnum.DEPT_1);
        List<SysDeptEntity> levelTypeTwo = filterByParentAndDept2(deptList, levelTypeOne);
        List<SysDeptEntity> levelTypeAPP = filterByParentAndDept99(deptList, levelTypeTwo);
        //一级
        getSaveUpdateDept(levelTypeOne, levelTypeOneProvince, deptIdLong);
        //二级
        getSaveUpdateDept(levelTypeTwo, levelTypeTwoProvince, deptIdLong);
        //应用
        getSaveUpdateDept(levelTypeAPP, levelTypeAPPProvince, deptIdLong);
        //应用 部门和应用同一个事务中
    }

    /**
     * 更新插入
     *
     * @param local
     * @param province
     */
    public void getSaveUpdateDept(List<SysDeptEntity> local, List<SysDeptEntity> province, Long levelDept) {
        Map<String, SysDeptEntity> collect = province.stream().collect(Collectors.toMap(SysDeptEntity::getUniqueId, a -> a, (k1, k2) -> k1));
        for (SysDeptEntity sysDeptEntity : local) {
            SysDeptEntity deptEntity = new SysDeptEntity();
            BeanUtils.copyProperties(sysDeptEntity, deptEntity);
            //监管平台的数据
            SysDeptEntity entity = collect.get(levelDept + "-" + deptEntity.getDeptId());
            //本地的父类id
            SysDeptEntity querySysDept = new SysDeptEntity();
            querySysDept.setUniqueId(levelDept + "-" + deptEntity.getParentId());
            String parentStr = HttpClientUtils.postHttp(server + OuterServerUrlConstant.DEPT_INFO, JSON.toJSONString(querySysDept));
            SysDeptEntity parentDept = JSON.parseObject(parentStr, SysDeptEntity.class);
            //转化为监管平台的父类
            deptEntity.setParentId(parentDept.getDeptId());

            deptEntity.setUniqueId(levelDept + "-" + deptEntity.getDeptId());

            if (entity != null) {
                //更新
                deptEntity.setDeptId(entity.getDeptId());

                ResponseEntity responseEntity = HttpClientUtils.postHttpResult(server + OuterServerUrlConstant.DEPT_UPDATE, JSON.toJSONString(deptEntity));
                logger.info("机构更新 ："+JSON.toJSONString(responseEntity));

            }
            if (entity == null) {
                deptEntity.setDeptId(null);
                //插入
                ResponseEntity responseEntity = HttpClientUtils.postHttpResult(server + OuterServerUrlConstant.DEPT_SAVE, JSON.toJSONString(deptEntity));
                logger.info("机构保存 ："+JSON.toJSONString(responseEntity));

            }
        }

    }

    public List<SysDeptEntity> filterByParentAndDept2(List<SysDeptEntity> allList, List<SysDeptEntity> levelTypeOne) {
        List<Long> parentIds = levelTypeOne.stream().map(a -> a.getDeptId()).collect(Collectors.toList());
        return filterByParentAndDept(allList, parentIds, Constant.DeptTypeEnum.DEPT_2);
    }

    public List<SysDeptEntity> filterByParentAndDept99(List<SysDeptEntity> allList, List<SysDeptEntity> levelTypeOne) {
        List<Long> parentIds = levelTypeOne.stream().map(a -> a.getDeptId()).collect(Collectors.toList());
        return filterByParentAndDept(allList, parentIds, Constant.DeptTypeEnum.APP);
    }

    /**
     * 筛选部门
     *
     * @param list
     * @param deptIds
     * @param deptTypeEnum
     * @return
     */


    public List<SysDeptEntity> filterByParentAndDept(List<SysDeptEntity> list, List<Long> deptIds, Constant.DeptTypeEnum deptTypeEnum) {
        return list.stream().filter(a -> deptIds.contains(a.getParentId()) && a.getType().equals(deptTypeEnum.getValue())).collect(Collectors.toList());
    }
}
